// "Just enough" unicode support

#ifdef TARGET_WIN32
#include <wchar.h>
#include <string.h>
#else
#endif

#include "unicode.h"
#include "util.h"

extern "C" char get_char_category(unsigned ch);
extern "C" unsigned simple_casefold_char(unsigned ch);
extern "C" unsigned get_combining_class(unsigned ch);


bool IsAlphabetic(wxChar c)
{
    char prop = get_char_category(c);
    return prop<4 || prop==9;

/*
    Alphabetic = Lu + Ll + Lt + Lm + Lo + Nl

    categories={'Lu':0, 'Ll':1, 'Lt':2, 'Lm':3, 'Lo':4, \
                'Mn':5, 'Me':6, 'Mc':7, \
                'Nd':8, 'Nl':9, 'No':10, \
                'Zs':11, 'Zl':12, 'Zp':13, \
                'Cc':14, 'Cf':15, 'Co':16, 'Cs':17, 'Cn':18, \
                'Pd':19, 'Ps':20, 'Pe':21, 'Pc':22, 'Po':23, 'Pi':24, 'Pf':25, \
                'Sm':26, 'Sc':27, 'Sk':28, 'So':29}
*/
}

bool IsBlankChar(wxChar c)
{
    return (c==' ') || (c=='\t');
}

bool IsWhitespaceChar(wxChar c)
{
    return c==' ' || c=='\n' || c=='\t';
}

bool IsKeywordChar(wxChar c)
{
    if (c>=128)
        return IsAlphabetic(c);
    return (c >='a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c=='.') || (c=='-');
}

int wxCharCmpI(wxChar a1, wxChar a2)
{
    wxChar c1 = simple_casefold_char(a1);
    wxChar c2 = simple_casefold_char(a2);
    if (c1 < c2)
        return -1;
    if (c1 > c2)
        return +1;
    return 0;
}

int wxStrCmpI(const wxString& str1, const wxString& str2)
{
    unsigned minlen = str1.Len();
    if (str2.Len() < minlen) minlen = str2.Len();

    for (unsigned x=0; x<str1.Len(); x++) {
        wxChar c1 = simple_casefold_char(str1[x]);
        wxChar c2 = simple_casefold_char(str2[x]);
        if (c1 < c2)
            return -1;
        if (c1 > c2)
            return +1;
    }
    if (str1.Len() < str2.Len())
        return -1;
    else if (str1.Len() > str2.Len())
        return +1;
    else
        return 0;
}

bool wxString_ContainsI(const wxString& str1, const wxString& str2, int from, int to)
{
    return wxNOT_FOUND != wxString_FindI(str1, str2, from, to);
}

int wxString_FindI(const wxString& str1, const wxString& str2, int from, int to)
{
    int len1 = str1.Len();
    int len2 = str2.Len();
    if (len1 == 0) return wxNOT_FOUND;
    wxASSERT(len2 > 0);

    // get search bounds
    wxASSERT(from == 0   || (from >= 0 && from < len1));
    wxASSERT(to   == -1  || (to > from && to <= len1));
    int search_from = from;
    int search_to = (to == -1) ? len1 : to;
    int search_len = search_to - search_from;

    if (len2 > search_len)
        return wxNOT_FOUND;

    for (int i=search_from; i<=search_to-len2; i++) {
        int x;
        for (x=0; x<len2; x++) {
            wxChar c1 = simple_casefold_char(str1[i+x]);
            wxChar c2 = simple_casefold_char(str2[x]);
            if (c1 != c2)
                break;
        }
        if (x==len2)
            return i;
    }
    return wxNOT_FOUND;
}

// TODO: we need some kind of conversion to remove combining characters
// copy-pasted string from http://www.worldcat.org/title/robotnicka-trieda-v-boji-proti-fasizmu-na-slovensku-1938-1941/oclc/179177047
// contains combining characters
bool wxString_CheckCombining(const wxString& str)
{
    unsigned seq_start, x;
    for (unsigned i=0; i<str.Len(); i++) {
        if (get_combining_class(str[i])) {
            wxString sequence;
            wxString character;
            for (seq_start=i; seq_start>0 && get_combining_class(str[seq_start]); seq_start--);
            x = seq_start;

            if (get_combining_class(str[seq_start]) == 0) {
                sequence = wxFormat("\tU+%04X\t%c", str[x], str[x]);
                character = str[x];
                x++;
            } else {
                sequence = "<No base character>";
                character = " ";
            }
            for (; x<str.Len() && get_combining_class(str[x]); x++) {
                sequence += wxFormat("\n\tU+%04X\t %c", str[x], str[x]);
                character += str[x];
            }
            ErrMsg("Found combining char U+%04X at position %u.\nCombining characters on input are unsupported by this application. "
                   "If this is how your system inputs regular characters in your language, please contact the author of HINT.\n"
                   "\n\nFull grapheme:\n\n\t%s\n\nUnicode sequence: (from position %d)\n%s",
                    str[i], i, character, seq_start, sequence);
            return true;
        }
    }
    return false;
}
